<cfcomponent output="false">
	
	<!--- --->
	
	<cffunction name="init" access="public" output="true" returntype="void">
		
		<!--- do nothing for now. --->

	</cffunction>
	
	<!--- --->
	
	<cffunction name="startOfRequest" access="public" output="true" returntype="void">
		
		<cfset var local = {} />
		
		<!--- get a cookie, which is linked to a session. --->
		<cfset local.id = getCookie() />
		
		<!--- get the companion session from cookie --->
		<cfset local.sessionRecord = loadSessionFromDB(local.id) />
		
		<!--- reset the cookie and try the above again, if no session matching cookie is found --->
		<cfif local.sessionRecord.recordcount eq 0>
			<cfcookie name="c24" value="-1" expires="now" />
			<cfset local.sessionRecord = loadSessionFromDB(getCookie()) />
		</cfif>
		
		<!--- so you found a session, check the keys to make sure they all exist, if not, log in again --->
		<cfif local.sessionRecord.recordcount gt 0 and local.sessionRecord.user_id neq "">
			<cfset local.sessionTemplate = getSessionTemplate() />
			<cfset local.sessionRecordStruct = deserializeJSON(local.sessionRecord.json) />
			<cfset local.reload = false />
			<cfloop collection="#local.sessionTemplate.user#" item="local.key" index="local.i">
				<cfif not structKeyEXists(local.sessionRecordStruct,local.i)>
					<cfset local.reload = true />
				</cfif>
				<cfif local.reload>
					<!--- invalidate cache on this user --->
					<cfset local.user = $.run.it('craftivityService.getUser',{userID=local.sessionRecord.user_id,invalidateCache=true}) />
					<!--- update request with user values --->
					<cfset request.session.id = local.sessionRecord.id />
					<cfset application.session.pushUserToSession(local.user) />
				</cfif>
			</cfloop>
		</cfif>
		
		<!--- as a catch all, if local.session is still empty load the session template --->
		<cfif local.sessionRecord.recordcount eq 0>
			<cfset local.session = getSessionTemplate() />
			<cfset local.session.id = '-1' />
		<cfelse>
			<cfset local.session = {} />
			<cfif local.sessionRecord.json neq "">
				<cfset local.session.user = deserializeJSON(local.sessionRecord.json) />
			<cfelse>
				<cfset local.session.user = {
					id=""
				} />
			</cfif>
			<cfset local.session.id = local.sessionRecord.id>
		</cfif>
		
		<!--- load options based on userID (if it even exists) --->
		<cfset local.options = application.s.optionService.loadOptions(local.session.user.id) />

		<!--- set session and options in request scope for everything else to use --->
		<cfset request.session = local.session />
		<cfset request.options = local.options />

	</cffunction>
	
	<!--- --->
	
	<cffunction name="getCookie" access="private" output="true" returntype="string">
				
		<cfset var local = {} />

		<!--- if no cookie exists, create a session, and link it to a cookie --->
		<cfif not structKeyExists(cookie,'c24') or len($.format.decrypt(cookie.c24)) neq 32>
			<cfset local.session = getSessionTemplate() />
			<cfset local.id = $.database.save(
				table="session",id="",json=serializeJSON(local.session.user)
			) />
			<cfcookie name="c24" expires="never" value="#$.format.encrypt(local.id)#" />
		<cfelse>
			<cfset local.id = $.format.decrypt(cookie.c24) />
			<!--- update modified on session to indicate activity --->
			<cfset $.database.save(
				table="session",
				id=local.id,
				active=1
			) />
		</cfif>
		
		<cfreturn local.id />

	</cffunction>
	
	<!--- --->
	
	<cffunction name="loadSessionFromDB" access="public" output="true" returntype="query">
		<cfargument name="id" required="true" />
				
		<cfset var local = {} />
		
		<cfquery name="local.loadSessionFromDB" datasource="#$.site.getVar('datasource')#">
			select
			hex(session.id) as id,
			hex(user_id) as user_id,
			now() as now,
			json,
			date_format(session.modified,'%m/%d/%Y %H:%i:%s') as modified
			from session
			where session.active = 1
			and id = #$.database.uuid(arguments.id)#
			<!--- sessions don't expire, ever --->
			<!--- and session.modified + interval #timeoutinminutes# minute > now() --->
			order by session.modified desc
			limit 1
		</cfquery>

		<cfreturn local.loadSessionFromDB />

	</cffunction>
	
	<!--- --->
	
	<cffunction name="getSessionTemplate" access="private" output="true" returntype="struct">
		
		<cfset var local = {} />
		<!--- define what a session looks like --->
		
		<cfset local.session = {} />
		<cfset local.session.user = {} />
		<cfset local.session.user.id = "" />
		<cfset local.session.user.name = "" />
		<cfset local.session.user.timezone = "-6:00" />
		<cfset local.session.user.DST = "true" />
		<!--- <cfset local.session.user.expireUTC = dateTimeFormat('01/01/2020','mm/dd/yyyy HH:nn:ss') />
		<cfset local.session.user.sessionExpires = dateTimeFormat('01/01/2020','mm/dd/yyyy HH:nn:ss') /> --->
		<cfset local.session.user.admin = 0 />
		<cfset local.session.user.event_categories = "" />
		<cfset local.session.user.agreement = 0 />
				
		<cfreturn local.session />
		
	</cffunction>
	
	<!--- --->
	
	<cffunction name="pushUserToSession" access="public" output="true" returntype="string">
		<cfargument name="user" required="false" type="query" />
		
		<cfset var local = {} />
		
		<!--- if query for user is valid --->
		<cfif structKeyExists(arguments,'user') and arguments.user.recordcount gt 0>
			<cfset local.json.id = arguments.user.id />
			<cfset local.json.name = arguments.user.first_name & ' ' & arguments.user.last_name />
			<cfset local.json.timezone = arguments.user.timezone />
			<cfset local.json.dst = 1 />
			<cfif arguments.user.dst eq 0>
				<cfset local.json.dst = 0 />
			</cfif>
			<cfset local.json.admin = 0 />
			<cfif arguments.user.admin eq 1>
				<cfset local.json.admin = 1 />
			</cfif>
			<cfif local.json.timezone eq ""><cfset local.json.timezone = "-6:00"></cfif>
			<cfset local.json.event_categories = "" />
			<cfif arguments.user.event_categories neq "">
				<cfset local.json.event_categories = arguments.user.event_categories />
			</cfif>
			<cfset local.json.agreement = arguments.user.agreement />
			
			<cfset local.serializedJSON = serializeJSON(local.json) />
			
			<!--- set user --->
			<cfset local.userID = arguments.user.id />
			<cfset request.session.user = local.json />
		<cfelse>
		<!--- if invalid user query, or no records --->
			<!--- get session template --->
			<cfset local.template = getSessionTemplate() />
			
			<!--- set user --->
			<cfset local.userID = "" />
			<cfset request.session.user = local.template.user />
			<cfset local.serializedJSON = "" />
		</cfif>

		<!--- update session record --->
		<cfset local.id = $.database.save(
			table="session",
			id=request.session.id,
			user_id=local.userID,
			json=local.serializedJSON
		) />
		<cfreturn true />
		
	</cffunction>
	
	<!--- --->
	
</cfcomponent>